using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Rocuna.Core.Exceptions;

namespace Rocuna.Controls
{
    /// <summary>
    /// JoystickBase control (designed for WP7)
    /// </summary>
    public abstract class JoystickBase : Control
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="Control"/> class.
        /// </summary>
        /// <param name="game">The Game that the game component should be attached to.</param>
        public JoystickBase(Game game)
            : base(game)
        {
            DrawOrder = int.MaxValue;
            InActiveCommand = new List<Action<EventArgs>>();
        }

        #region Properties

        /// <summary>
        /// Occurs when drag.
        /// </summary>
        public event EventHandler Drag;

        protected virtual void RaiseDragEvent(object o)
        {
            if (Drag != null)
                Drag(this, o as EventArgs);
        }

        /// <summary>
        /// Occurs when [drag end].
        /// </summary>
        public event EventHandler DragEnd;

        protected virtual void RaiseEndDragEvent(object o)
        {
            if (DragEnd != null)
                DragEnd(this, o as EventArgs);
        }

        /// <summary>
        /// List Of Actions to preform when joytick is in active state.
        /// </summary>
        protected List<Action<EventArgs>> InActiveCommand { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is active.
        /// </summary>
        /// <value>
        ///   <c>true</c> if this instance is active; otherwise, <c>false</c>.
        /// </value>
        protected bool IsActive;

        protected EventArgs ActiveArgs;

        /// <summary>
        /// Sets the state of the active.
        /// </summary>
        /// <param name="args">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        public virtual void SetActiveState(EventArgs args)
        {
            IsActive = true;
            ActiveArgs = args;
        }

        /// <summary>
        /// Deactives the state.
        /// </summary>
        public virtual void DeactiveState()
        {
            IsActive = false;
        }

        /// <summary>
        /// Registers the command.
        /// </summary>
        /// <param name="action">The action.</param>
        public virtual void RegisterCommand(Action<EventArgs> action)
        {
            InActiveCommand.Add(action);
        }

        /// <summary>
        /// Unregisters the command.
        /// </summary>
        /// <param name="action">The action.</param>
        public virtual void UnregisterCommand(Action<EventArgs> action)
        {
            InActiveCommand.Remove(action);
        }

        /// <summary>
        /// Clears the commands.
        /// </summary>
        public virtual void ClearCommands()
        {
            InActiveCommand.Clear();
        }

        #endregion

        #region Methods

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);
            if (IsActive)
                foreach (var action in InActiveCommand)
                {
                    action(ActiveArgs);
                }
        }

        /// <summary>
        /// Raises the drag event.
        /// </summary>
        /// <param name="args">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        public void RaiseDragEvent(EventArgs args)
        {
            if (Drag != null)
                Drag(this, args);
        }

        public override void Draw(GameTime gameTime)
        {
            var spriteBatch = Game.Services.GetService(typeof(SpriteBatch)) as SpriteBatch;
            if (spriteBatch == null)
                throw new NotInitializedException();
            spriteBatch.Begin();
            if (Foreground != null)
                spriteBatch.Draw(Foreground, Border.ToRectangle(), Background);
            spriteBatch.End();
            base.Draw(gameTime);
        }

        #endregion
    }
}